<!-- 表单设计 -->
<template>
  <div ref="bod">
    <div ref="content" class="formDesign-content">
      <!-- 控件栏 start -->
      <div
        class="controlCont"
        :class="{ procedureTemplate: true, topShow: topShow }"
      >
        <div class="title">
          <div>表单控件</div>
          <!-- <t-input placeholder="请输入">
            <template #suffixIcon>
              <span class="t-icon t-icon-search"></span>
            </template>
          </t-input> -->
        </div>
        <div class="items-wrap">
          <div
            v-for="(item, index) in itemsDataes"
            :ref="`it` + index"
            :key="index"
            class="items"
            :class="{ title: item.type === 'title' }"
            @mousedown="mouseDown(item)"
          >
            <div
              v-if="item.type != 'title'"
              class="iconfont"
              :class="[item.icon]"
            ></div>
            <div>{{ item.lab }}</div>
          </div>
          <div v-show="isdrag" class="drag" :style="{ left: left, top: top }">
            <div class="iconfont" :class="[dragData.icon]"></div>
            <div>{{ dragData.lab }}</div>
          </div>
        </div>
      </div>
      <!-- 控件栏 end -->
      <!-- // 控件展示区 - start -->
      <div class="showScreen">
        <div class="actionTab">
          <div class="fx-ct">
            <!-- <span class="icon"></span><span class="iconRt"></span> -->
          </div>
          <div class="fx-ct">
            <span
              class="iconfont btn_mobile_nor2x"
              :class="{ active: showScreen === 'phon' }"
              @click="screenHandle('phon')"
            ></span
            ><span
              class="iconfont btn_pc_nor2x"
              :class="{ active: showScreen === 'pc' }"
              @click="screenHandle('pc')"
            ></span>
          </div>
        </div>
        <div
          ref="phContDom"
          class="phoneContent"
          :class="{ PCContent: showScreen === 'pc' }"
        >
          <div v-if="phDataes.length > 0" ref="phScroll" class="phoneShow">
            <div
              v-for="(it, index) in phDataes"
              :key="index"
              class="phItems"
              :style="{ width: setWith(it) }"
              @mousedown="phMouseDown(it, index)"
              @click.stop="openSet(index)"
            >
              <div
                v-if="it !== 'empty'"
                :class="{
                  phItem: true,
                  mov: actId === index,
                  act: actInd === index && !isdrag,
                  over: actId !== index
                }"
              >
                <!-- 这里是控件内容 后面可能要根据不同的控件类型进行处理 - start -->
                <div>
                  <div class="tit">
                    <span
                      v-show="it.data.isMust"
                      class="mast"
                      style="color: #f00"
                      >*</span
                    >
                    <span v-if="it.data.isShowTitle">
                      {{ it.data.title || it.lab }}
                    </span>
                    &nbsp;
                  </div>
                  <div
                    v-if="
                      it.type !== 'rate' &&
                      it.type !== 'switch' &&
                      it.type !== 'slider' &&
                      it.type !== 'file' &&
                      it.type !== 'img' &&
                      it.type !== 'dateArea' &&
                      it.type !== 'subform' &&
                      it.type !== 'line' &&
                      it.type !== 'location' &&
                      it.type !== 'button'
                    "
                    class="lab"
                  >
                    {{
                      typeof it.data.defaultValue === 'string' &&
                      it.data.defaultValue
                        ? it.data.defaultValue
                        : it.data.placeholder
                    }}
                  </div>
                  <div
                    v-if="it.data.isStatistics && it.type !== 'rate'"
                    class="total"
                  >
                    {{
                      Number(it.data.defaultValue.length) ||
                      Number(it.data.minLength) ||
                      0
                    }}/{{ Number(it.data.maxLength) || 0 }}
                  </div>
                  <!-- 评分卡片独有的展示形式 -->
                  <div v-if="it.type === 'rate'" class="lab">
                    <t-rate
                      v-model="attributeset.data.defaultValue"
                      disabled
                      allowHalf
                      size="20px"
                    ></t-rate>
                  </div>
                  <!-- 开关独有的展示形式 -->
                  <div v-if="it.type === 'switch'" class="lab">
                    <t-switch
                      v-model="attributeset.data.defaultValue"
                      disabled
                      size="20px"
                    ></t-switch>
                  </div>
                </div>
                <!-- 滑块独有的展示形式 -->
                <div v-if="it.type === 'slider'" class="lab">
                  <t-slider
                    v-model="attributeset.data.defaultValue"
                    :step="attributeset.data.step"
                    disabled
                    size="small"
                  />
                </div>
                <!-- 日期区间的展示形式 -->
                <div v-if="it.type === 'dateArea'" class="lab">
                  <span
                    v-if="
                      Array.isArray(attributeset.data.defaultValue) &&
                      attributeset.data.defaultValue.length >= 1
                    "
                    >{{ attributeset.data.defaultValue[0] }} -
                    {{ attributeset.data.defaultValue[1] }}</span
                  >
                  <span v-else>请选择 - 请选择</span>
                </div>
                <!-- 附件和图片的展示形式 -->
                <div
                  v-if="it.type === 'file' || it.type === 'img'"
                  class="lab"
                ></div>
                <!-- 子表单控件内容 -->
                <div
                  v-if="it.type === 'subform'"
                  class="subformlab"
                  style="padding-top: 10px"
                >
                  <SubForm :data="it.data.formData"></SubForm>
                </div>
                <!-- 省市区控件内容 -->
                <div v-if="it.type === 'location'" class="lab">
                  {{
                    typeof it.data.defaultValue === 'string' &&
                    it.data.defaultValue
                      ? cityCodeToName(it.data.defaultValue)
                      : it.data.placeholder
                  }}
                </div>
                <!-- 分割线区控件内容 -->
                <div
                  v-if="it.type === 'line'"
                  :style="{
                    position: `relative`,
                    margin: '10px 0 3px 0',
                    borderTop: `${it.data.type} ${it.data.height}px ${it.data.color}`
                  }"
                >
                  <span
                    style="
                      position: absolute;
                      left: 50%;
                      padding: 0 10px;
                      line-height: 22px;
                      transform: translate(-50%);
                      background: #fff;
                    "
                    :style="{ top: `-${11 + it.data.height / 2}px` }"
                    >{{ it.data.placeholder }}</span
                  >
                </div>
                <!-- 部门控件内容 -->
                <!-- <div v-if="it.type === 'department'" class="lab"></div> -->
                <!-- 人员控件内容 -->
                <!-- <div v-if="it.type === 'member'" class="lab"></div> -->

                <!-- 按钮控件内容 -->
                <div v-if="it.type === 'button'" style="margin-top: 5px">
                  <t-button size="small">{{ it.data.name }}</t-button>
                </div>
                <!-- 这里是控件内容 后面可能要根据不同的控件类型进行处理 - end -->
                <div class="actions">
                  <icon-font size="0px" name="t-icon-file-copy" />
                  <span
                    class="t-icon t-icon-file-copy"
                    @click.stop="copyNode(it)"
                  ></span>
                  <span class="line"></span>
                  <span
                    class="iconfont icon_delete2x"
                    @click.stop="delNode(index)"
                  ></span>
                </div>
              </div>
              <div v-if="it === 'empty'" class="phEmpty"></div>
            </div>
          </div>
          <div v-else class="phItemEmpty">
            <img
              src="./../../../assets/flowImg/empty.png"
              alt="请将左侧控件拖拽到本区域进行编辑"
            />
            <span>请将左侧控件拖拽到本区域进行编辑</span>
          </div>
        </div>
      </div>
      <!-- // 控件展示区 - end -->
      <!-- 控件属性区 - start -->
      <div class="ctrlContent" :class="{ setParamsBox: true, setShow: true }">
        <keep-alive v-if="phDataes.length > 0 && attributeset">
          <component
            :is="attrName"
            :arrtData="attributeset"
            @changeAttrHandle="changeAttrHandle"
          ></component>
        </keep-alive>
        <div v-else class="fx-ct ctrlEmpty">请选择组件</div>
      </div>
      <!-- 控件属性区 - start -->
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, shallowRef, onMounted, watch } from 'vue'
import { IconFont } from 'tdesign-icons-vue-next'
import { useFormData } from '@/store'
import SubForm from './SubForm.vue'
import { cityCodeToName } from './attrComponents/addressList'

// 属性面板 - 数据、模块 引入
import {
  Input,
  TextArea,
  Radio,
  Checkbox,
  Select,
  TimeSelect,
  NumberInput,
  DateArea,
  Rate,
  Switch,
  Slider,
  FileUpload,
  ImgUpload,
  Position,
  ProvincesArea,
  DivisionLine,
  Button,
  Department,
  Subform,
  Member,
  Location,
  Line
} from './attrComponents/index'
import fromCtrlDataes from './formCtrl'

const store = useFormData()

const attrName = shallowRef()

const topShow = ref(true)
const setShow = ref(false)
const setTit = ref('属性设置')
const type = ref('input')
const isdrag = ref(false)
const left = ref()
const top = ref()
const mouseX = ref(0)
const mouseY = ref(0)
const fixedTop = ref(62) // 顶部固定高
const fixedLeft = ref(0) // 左侧的便宜
const fixedX = ref(0) // 鼠标起始值 X
const fixedY = ref(0) // 鼠标起始值 X
const movInd = ref() // 被点击框的位置
const movToInd = ref(0) // 移动到位置的index
const phx1 = ref(0) // 手机位置
const phx2 = ref(0)
const phy1 = ref(0)
const phy2 = ref(0)
const actId = ref() // 当前选择项位置
const fixedId = ref('') // 起始点位置
const actInd = ref() // 被点击项
const oldMove = ref(0) // 上次位移
const movSt = ref(true)
const dragData = ref({}) // 被移动框的数据
const attributeset = ref()
const phDataes = ref([])
const itemsDataes = ref([])

// 属性面板切换
const attrChangeHandle = (tag) => {
  switch (tag) {
    case 'input':
      attrName.value = Input
      break
    case 'textArea':
      attrName.value = TextArea
      break
    case 'radio':
      attrName.value = Radio
      break
    case 'checkbox':
      attrName.value = Checkbox
      break
    case 'select':
      attrName.value = Select
      break
    case 'timeSelect':
      attrName.value = TimeSelect
      break
    case 'number':
      attrName.value = NumberInput
      break
    case 'dateArea':
      attrName.value = DateArea
      break
    case 'rate':
      attrName.value = Rate
      break
    case 'switch':
      attrName.value = Switch
      break
    case 'slider':
      attrName.value = Slider
      break
    case 'file':
      attrName.value = FileUpload
      break
    case 'img':
      attrName.value = ImgUpload
      break
    case 'position':
      attrName.value = Position
      break
    case 'provincesArea':
      attrName.value = ProvincesArea
      break
    case 'divisionLine':
      attrName.value = DivisionLine
      break
    case 'button':
      attrName.value = Button
      break
    case 'department':
      attrName.value = Department
      break
    case 'member':
      attrName.value = Member
      break
    case 'subform':
      attrName.value = Subform
      break
    case 'location':
      attrName.value = Location
      break
    case 'line':
      attrName.value = Line
      break
    default:
      attrName.value = Input
      break
  }
}

const props = defineProps({
  initData: Object
})

const showScreen = ref('phon')
onMounted(() => {
  // 获取到 bod相对于窗口的位置
  const bodPoint = bod.value.getBoundingClientRect()
  fixedTop.value = bodPoint.top
  fixedLeft.value = bodPoint.left
  init()
  phCont()
  itemsDataes.value = fromCtrlDataes
})

const screenHandle = (val) => {
  showScreen.value = val
}

// 动态处理控件宽度
const setWith = (val) => {
  let widthVal = 100
  if (val !== 'empty' && showScreen.value === 'pc') {
    widthVal = val.data.width
  }
  return `calc(${widthVal}% - 5px)`
}

const init = async () => {
  if (Object.keys(props.initData.formData).length > 0) {
    phDataes.value = props.initData.formData[0].data
    attributeset.value = phDataes.value[0]
    openSet(0)
  }
}

// 鼠标抬起的时候 - 所有的移动 点击的都走这个
const content = ref()
const mouseUp = () => {
  console.log('鼠标抬起的时候')
  isdrag.value = false
  movSt.value = false
  actId.value = ''
  // 识别添加并指定添加或者移动的位置
  if (phDataes.value.indexOf('empty') !== -1) {
    phDataes.value.splice(phDataes.value.indexOf('empty'), 1)
    dragDataHandle() // 给本条数据添加id
    phDataes.value.splice(
      movToInd.value,
      0,
      JSON.parse(JSON.stringify(dragData.value))
    )
    if (movInd.value !== 'add') {
      phDataes.value.splice(
        movInd.value < movToInd.value ? movInd.value : movInd.value + 1,
        1
      )
      actInd.value =
        movInd.value < movToInd.value ? movToInd.value - 1 : movToInd.value
    }
  }
  content.value.onmousemove = ''
  bod.value.onmouseup = null

  if (movInd.value === 'add') {
    attributeset.value = phDataes.value[phDataes.value.length - 1]
    openSet(phDataes.value.length - 1)
    return null
  }

  attributeset.value = dragData.value
}

// 控件 - 鼠标按下的时候 进行处理
const stTime = ref()
const catchData = ref()

const mouseDown = (item) => {
  console.log('鼠标按下的时候执行')
  if (item.type === 'title') {
    return
  }
  stTime.value = new Date()
  catchData.value = JSON.parse(JSON.stringify(item))
  const x = event.clientX
  const y = event.clientY
  const lx = event.layerX
  const ly = event.layerY
  movInd.value = 'add'
  mouseX.value = lx
  mouseY.value = ly
  top.value = `${y - ly - fixedTop.value}px`
  left.value = `${x - lx - fixedLeft.value}px`
  content.value.onmousemove = mouseMove
  content.value.onmouseup = mouseToUp
}
// 主要处理 鼠标点击 (默认的200ms之内松开鼠标) 直接加入
const mouseToUp = () => {
  const endTime = new Date()
  const dateDiff = endTime.getTime() - stTime.value.getTime()
  if (dateDiff < 200) {
    phDataes.value.push('empty')
    movInd.value = 'add'
    movToInd.value = phDataes.value.length - 1
    dragData.value = catchData.value
    mouseUp()
    setTimeout(() => {
      scrollBottom()
    }, 100)
  }
}
// 鼠标移动操作
const bod = ref()
const mouseMove = (e) => {
  dragData.value = catchData.value
  isdrag.value = true
  const x = e.clientX - fixedLeft.value
  const y = e.clientY - fixedTop.value
  top.value = `${y - mouseY.value}px`
  left.value = `${x - mouseX.value}px`
  movSt.value = true
  moveCheck(x, y)
  bod.value.onmouseup = mouseUp
}

// 中间展示区域 按下的处理
const phMouseDown = (item, i) => {
  phCont()
  type.value = item.type
  fixedX.value = event.clientX
  fixedY.value = event.clientY
  movInd.value = i
  attributeset.value = item
  setTit.value = item.lab
  movSt.value = true
  dragData.value = item
  content.value.onmousemove = phmouseMove
  bod.value.onmouseup = mouseUp
}
// 中间展示区域 移动操作
const phmouseMove = (event) => {
  const x = event.clientX
  const y = event.clientY
  top.value = `${y - 16 - fixedTop.value}px`
  left.value = `${x - 74 - fixedLeft.value}px`
  moveCheck(x, y)
  bod.value.onmouseup = mouseUp
}
// 移动处理
const phScroll = ref()
const moveCheck = (x, y) => {
  if (x < phx1.value || x > phx2.value) {
    if (phDataes.value.indexOf('empty') !== -1) {
      phDataes.value.splice(phDataes.value.indexOf('empty'), 1)
      movSt.value = true
    }
    return false
  }
  if (fixedY.value === 0 || Math.abs(y - fixedY.value) > 2) {
    const st = 158
    const scNode = phScroll
    const num = (y + scNode.scrollTop - 158) / 48
    const end =
      phDataes.value.length * 48 < 560
        ? phDataes.value.length * 48 + 158
        : 560 + 158
    if (y < st) {
      fixedId.value = 0
      movToInd.value = 0
      scNode.scrollTop = 0
    } else if (y > end) {
      movToInd.value = phDataes.value.length - 1
      fixedId.value = movToInd.value
      scNode.scrollTop = phDataes.value.length * 48 - 500
    } else {
      movToInd.value = Math.round(num)
      fixedId.value = fixedY.value ? Math.round((fixedY.value - 138) / 48) : ''
    }
    isdrag.value = true
    if (movSt.value && phDataes.value.indexOf('empty') === -1) {
      oldMove.value = movToInd
      phDataes.value.splice(movToInd, 0, 'empty')
      movSt.value = false
    } else {
      phDataes.value.splice(phDataes.value.indexOf('empty'), 1)
      phDataes.value.splice(movToInd.value, 0, 'empty')
      oldMove.value = movToInd.value
    }
    if (fixedY.value && phDataes.value.indexOf('empty') !== -1) {
      actId.value =
        fixedId.value > movToInd.value ? movInd.value + 1 : movInd.value
    }
  }
}
// 删除节点逻辑
const delNode = (ind) => {
  if (actInd.value === ind) {
    actInd.value = ''
    setShow.value = false
  } else if (ind < actInd.value) {
    actInd.value -= 1
  }
  phDataes.value.splice(ind, 1)
  openSet(phDataes.value.length - 1)
}
// 拷贝
const copyNode = (item) => {
  const newData = { ...item }
  newData.id = Math.floor(Math.random() * 100000000000000)
  phDataes.value.push(newData)
  openSet(phDataes.value.length - 1)
}
// 打开某个数据 点击的时候 有问题 这个需要处理一下
const openSet = (i) => {
  actInd.value = i
  setShow.value = true
  if (attributeset.value.type) {
    attrChangeHandle(attributeset.value.type)
  }
}

// 记录手机位置
const phContDom = ref()
const phCont = () => {
  const stX = phContDom.value.offsetLeft - 296 / 2
  phx1.value = stX
  phx2.value = stX + 296
  phy1.value = 0
  phy2.value = document.body.offsetHeight - 68
}
// 移动数据处理
const dragDataHandle = () => {
  dragData.value.id = Math.floor(Math.random() * 100000000000000)
  // $store.dispatch("approval/getFileKeyAct").then(res => {
  //   dragData.fieldKey = res;
  // });
}
//fieldKey获取
const getFileKey = async () => {
  // await $store.dispatch("approval/getFileKeyAct").then(res => {
  //   itemData = res;
  // });
}
//
const labTitChang = (st, ind) => {
  if (typeof st === 'string' && st === 'add') {
    attributeset.value.data.titlab.push(
      `选项${attributeset.value.data.titlab.length + 1}`
    )
  } else if (typeof st === 'string' && st === 'sub') {
    attributeset.value.data.titlab.splice(ind, 1)
  } else {
    attributeset.value.data.titlab[ind] = st.target.value
  }
}

// 处理子组件的数据更改同步
const changeAttrHandle = (data) => {
  attributeset.value = { ...data }
}
// 滚动
const scrollBottom = () => {
  if (phScroll.value && phScroll.value.scrollTo) {
    phScroll.value.scrollTo({
      top: phScroll.value.scrollHeight,
      behavior: 'smooth'
    })
  }
}
// 监听整个表单的输入 并写入pina
watch(
  () => phDataes,
  (val) => {
    store.setFormData(val)
  },
  { deep: true }
)
</script>
<style src="../index.less" scoped></style>
